package main

import (
	m20 "github.com/metrics20/go-metrics20/carbon20"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	//"runtime"
	"fmt"
	logging "github.com/op/go-logging"
)

var (
	DEFAULT_CONFIG = "./conf/golia-relay.yml"
	DEFAULT_LOG    = "./log/golia-relay.log"
)

type Config struct {
	CarbonListenAddr       string   `yaml:"carbon_listen_addr"`
	WebListenAddr          string   `yaml:"http_listen_addr"`
	MondoAddr              string   `yaml:"mondo_addr"`
	EtcdAddr               []string `yaml:"etcd_addr"`
	CarbonAddrs            []string `yaml:"carbon_addrs"`
	KafkaAddr              []string `yaml:"kafka_addr"`
	KafkaTopic             string   `yaml:"kafka_topic"`
	logLevelStr            string   `yaml:"log_level"`
	validateLevelStr       string   `yaml:"validate_level"`
	ValidateOrder          bool     `ymal:"validate_order"`
	ReadBufferSize         int      `yaml:"read_buffer_size"`
	DataBufferSize         int      `yaml:"data_buffer_size"`
	CacheCleanInterval     int      `yaml:"cache_shrink_interval"`
	CacheSplitCount        int      `yaml:"cache_split_count"`
	CacheTimeUnit          int      `yaml:"cache_time_unit"`
	CacheMetricNames       []string `yaml:"cache_metric_names"`
	MetricNameConvertions  []string `yaml:"metric_name_convertions"`
	PrometheusMetricHead   []string `yaml:"prometheus_metric_head"`
	LogToFile              bool     `yaml:"log_to_file"`
	DebugMode              bool     `yaml:"debug_mode"`
	RetryMessageQueueSize  int      `yaml:"retry_message_queue_size"`
	ErrorReconnectTimes    int      `yaml:"error_reconnect_times"`
	ErrorReconnectInterval int      `yaml:"error_reconnect_interval"`
	ValidateLevel          m20.ValidationLevelM20
	LogLevel               logging.Level
}

func Load(s string) (*Config, error) {
	cfg := &Config{}
	if err := yaml.Unmarshal([]byte(s), cfg); err != nil {
		return nil, err
	}
	// if cfg.CacheLocalDir == "" {
	// 	cfg.CacheLocalDir = "./data"
	// }
	if cfg.CarbonListenAddr == "" || cfg.WebListenAddr == "" ||
		((len(cfg.KafkaAddr) == 0 || cfg.KafkaTopic == "") && cfg.DebugMode) {
		return nil, fmt.Errorf("missing somthing in conf")
	}
	if cfg.CacheTimeUnit == 0 {
		cfg.CacheTimeUnit = 7200
	}
	if cfg.CacheCleanInterval == 0 {
		cfg.CacheCleanInterval = 1200
	}
	if cfg.CacheSplitCount == 0 {
		cfg.CacheSplitCount = 3
	}
	return cfg, nil
}

func LoadFile(filename string) (*Config, error) {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	if cfg, err := Load(string(content)); err != nil {
		return nil, err
	} else {
		cfg.LoadLogLevel()
		cfg.LoadValidateLevel()
		return cfg, nil
	}
}

func (r *Config) LoadLogLevel() {
	switch r.logLevelStr {
	case "critical":
		r.LogLevel = logging.CRITICAL
	case "error":
		r.LogLevel = logging.ERROR
	case "warning":
		r.LogLevel = logging.WARNING
	case "notice":
		r.LogLevel = logging.NOTICE
	case "debug":
		r.LogLevel = logging.DEBUG
	default:
		r.LogLevel = logging.INFO
	}
}

func (r *Config) LoadValidateLevel() {
	switch r.validateLevelStr {
	case "strict":
		r.ValidateLevel = m20.StrictM20
	case "medium":
		r.ValidateLevel = m20.MediumM20
	default:
		r.ValidateLevel = m20.NoneM20
	}
}
